package com.bcx.wind.workflow.imp.cmd.corecmd;

import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.*;
import com.bcx.wind.workflow.core.flow.NodeModel;
import com.bcx.wind.workflow.core.flow.node.TaskNode;
import com.bcx.wind.workflow.entity.*;
import com.bcx.wind.workflow.pojo.Task;
import com.bcx.wind.workflow.pojo.Wind;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.pojo.variable.CompleteVariable;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.JsonHelper;
import com.bcx.wind.workflow.support.ObjectHelper;
import com.bcx.wind.workflow.support.TimeHelper;

import java.util.List;
import java.util.stream.Collectors;

import static com.bcx.wind.workflow.access.AccessSqlConstant.ORDER_ID;
import static com.bcx.wind.workflow.core.constant.Constant.WIND_ADMIN;
import static com.bcx.wind.workflow.message.ErrorCode.*;

/**
 * <p>
 * 完结流程，忽略后续所有任务节点的提交操作，直接将流程执行完毕。
 *
 * 主要操作逻辑：
 * 获取当前流程，以及当前任务。
 * 完成删除执行中的流程，以及流程中所有的任务，并将任务以及流程存储到历史表中。
 *
 * </p>
 *
 * @author zhanglei
 * @since 2019-04-28 09:13:22
 */
public class CompleteCommand extends BaseCommand {

    /**
     * 完结操作参数
     */
    private CompleteVariable variable;

    public CompleteCommand(CompleteVariable completeVariable){
        this.variable = completeVariable;
    }

    @Override
    public Wind execute() {
        wind().setOperate(WorkflowOperate.complete);
        //校验参数
        checkVariable();
        //实例化执行wind
        initWind();
        //当前任务节点
        withdrawAndCompleteCurNode();
        //执行完结操作
        completeOperate();
        return wind();
    }



    private  void  completeOperate(){
        String orderId = wind().getWindOrder().getId();
        //删除所有流程实例
        this.commandContext.access().removeOrderInstanceById(orderId);
        this.commandContext.access().removeOrderInstanceByParentId(orderId);
        //删除所有任务实例，以及任务审批人
        List<WindTask> tasks = this.commandContext.access().selectTaskInstanceList(new QueryFilter().setOrderId(orderId));
        this.commandContext.access().removeTaskByOrderId(orderId);
        this.commandContext.access().removeTaskActorByTaskIds(tasks.stream().map(WindTask::getId).collect(Collectors.toList()));

        //删除撤销暂存数据
        this.commandContext.access().deleteWindRevokeDataByOrderId(orderId);
        //添加流程实例履历
        this.commandContext.access().insertWindHistOrder(windHistOrder());

        //更新历史履历
        changeResume();
    }




    private WindHistOrder windHistOrder(){
        WindOrder windOrder = wind().getWindOrder();
        return new WindHistOrder()
                .setId(windOrder.getId())
                .setBusinessId(windOrder.getBusinessId())
                .setCreateTime(windOrder.getCreateTime())
                .setData(windOrder.getData())
                .setExpireTime(windOrder.getExpireTime())
                .setCreateUser(windOrder.getCreateUser())
                .setFinishTime(windOrder.getFinishTime())
                .setParentId(windOrder.getParentId())
                .setProcessId(windOrder.getProcessId())
                .setStatus(OrderStatus.complete.name())
                .setType(OrderType.main.name())
                .setSystem(windOrder.getSystem())
                .setVariable(windOrder.getVariable())
                .setVersion(windOrder.getVersion());
    }




    /**
     * 实例化执行数据集
     */
    private void initWind(){
        String orderId = this.variable.getOrderId();

        //流程实例
        WindOrder windOrder = buildWindOrder(orderId);
        //流程定义
        WindProcess windProcess = this.commandContext.repositoryService().queryById(windOrder.getProcessId());
        Assert.notEmptyError(PROCESS_QUERY_NULL,windProcess,windOrder.getProcessId());

        //所有任务实例
        QueryFilter filter = new QueryFilter()
                .setOrderId(orderId)
                .setStatus(TaskStatus.run.name())
                .setTaskLevel(TaskLevel.main.name());
        List<WindTask> windTasks = this.commandContext.access().selectTaskInstanceList(filter);
        Assert.notEmptyError(NOT_FOUND_TASK,windTasks);
        //多个任务不可完结
        Assert.isTrueError(COMPLETE_NOT_SUPPORT,windTasks.size() > 1);

        //所有配置
        getConfigList(windProcess.getId());

        wind().setWindOrder(windOrder)
                .setBusinessId(windOrder.getBusinessId())
                .setWindProcess(windProcess)
                .setUser(user())
                .setSystem(this.variable.getSystem())
                .setAllTasks(windTasks)
                .setSuggest(this.variable.getSuggest())
                .setArgs(this.variable.getArgs())
                .setWindConfig(buildWindConfig(buildProcessConfig()));


    }


    /**
     * 当前流程配置
     */
    private WindProcessConfig buildProcessConfig(){
        String processName = wind().getWindProcess().getProcessName();
        WindProcessConfig processConfig = ObjectHelper.getNodeConfig(this.configList,processName,this.variable.getArgs());
        Assert.notEmptyError(PROCESS_CONFIG_NOT_FOUND,processConfig,processName,processName);
        return processConfig;
    }




    /**
     * 校验完结参数
     */
    private void checkVariable(){
        String orderId = this.variable.getOrderId();
        Assert.notEmptyError(COMPLETE_FAIL,orderId,ORDER_ID);
    }


    /**
     * 当前用户  默认使用 wind_admin
     * @return  当前用户
     */
    private WindUser user(){
        WindUser user = this.variable.getUser();
        if(user == null){
            user = new WindUser()
                    .setUserId(WIND_ADMIN)
                    .setUserName("管理员");
        }
        return user;
    }
}
